场景:团队开发项目时,常常需要安装依赖,虽然一般使用文档可以说明。但不是比较强制的约束。(之前遇到一个项目在同事电脑安装依赖能运行,而我电脑安装依赖却跑不起来。后面发现是由于我node和npm的版本引起的安装依赖和运行项目失败了参考解决链接 )。假如规定是用的npm,团队中的某个同学使用其他包管理工具进行依赖的安装,且提交了。那么很大可能会直接影响到同时在该分支工作的其他同学,带来不必要的精力损耗。这时候我们可以借助工具(代码)来强制约束。
其中 Vue3 源码用了 npm 的 preinstall 钩子 约束,只能使用 pnpm 安装依赖。我们接着来看其实现:
Vue3 源码 && npm 命令钩子 1 2 3 4 5 6 7 8 { "private" : true , "version" : "3.2.22" , "scripts" : { "preinstall" : "node ./scripts/preinstall.js" , } }
1 2 3 4 5 6 7 依次执行# install 之前执行这个脚本 preinstall# 执行 install 脚本 install# install 之后执行这个脚本 postinstall
当然也支持自定义的命令。更多可以查看官方文档钩子
1 2 3 4 5 6 7 8 9 // vue-next /scripts/ preinstall.jsif (!/pnpm/ .test(process.env.npm_execpath || '' )) { console.warn( `\u001b[33 mThis repository requires using pnpm as the package manager ` + ` for scripts to work properly.\u001b[39 m\n` ) process.exit (1 ) }
这段代码也相对简单,校验如果不是 pnpm
执行脚本则报错,退出进程。
关于 process 对象可以查看 阮一峰老师 process 对象
process.argv 属性返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是 node,第二个成员是脚本文件名,其余成员是脚本文件的参数。
环境准备:克隆代码 1 2 3 4 5 git clone https://gi thub.com/pnpm/ only-allow.git cd only-allow pnpm i
Tips:开源项目一般先看README.md 。 readme
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 only-allow Force a specific package manager to be used on a project 强制在项目中使用特定的包管理器 Usage Add a preinstall script to your project's package.json. If you want to force npm, add : { "scripts" : { "preinstall" : "npx only-allow npm" } } If you want to force pnpm, add : { "scripts" : { "preinstall" : "npx only-allow pnpm" } } If you want to force yarn, add : { "scripts" : { "preinstall" : "npx only-allow yarn" } }
目录结构:
调试源码 查看 package.json 文件。
确定主入口文件为 only-allow/bin.js。
在最新版的 VSCode 中,auto attach 功能,默认支持智能调试,如果发现不支持,可以通过快捷键 ctrl + shift + p 查看是否启用。
于是我们在 only-allow/package.json 文件中,添加如下命令。
1 2 3 4 5 6 { "scripts" : { "preinstall" : "node bin.js pnpm" }, }
可以提前在 only-allow/bin.js 文件打上断点 const usedPM = whichPMRuns()
然后: 输入如下 yarn add release-it -D (或者 npm i) 命令,即可调试 only-allow/bin.js。
安装yarn可直接进入此电脑cmd输入安装命令:(npm install -g yarn)
查看版本:yarn –version
only-allow 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #!/usr/bin/env node const whichPMRuns = require('which -pm-runs') const boxen = require('boxe n') const argv = process.argv.slice(2 )if (argv.length === 0 ) { console.log('Please specify the wanted package manager: only-allow <npm|pnpm|yarn>') process.exit(1 ) } const wantedPM = argv[0 ]if (wantedPM !== 'np m' && wantedPM !== 'pnp m' && wantedPM !== 'yar n') { console.log(`"${wantedPM}" is not a valid package manager. Available package managers are: npm, pnpm, or yarn.`) process.exit(1 ) } const usedPM = whichPMRuns()if (usedPM && usedPM.name !== wantedPM) { const boxenOpts = { borderColor: 're d', borderStyle: 'doubl e', padding: 1 } switch (wantedPM) { case 'np m': console.log(boxen('Use "npm install" for installation in this project', boxenOpts)) break case 'pnp m': console.log(boxen(`Use "pnpm install" for installation in this project.If you don't have pnpm, install it via "npm i -g pnpm" .For more details, go to https: break case 'yar n': console.log(boxen(`Use "yarn" for installation in this project.If you don't have Yarn , install it via "npm i -g yarn" .For more details, go to https: break } process.exit(1 ) }
总结 通过本文,我们了解了 npm 的脚本钩子和 process 的简单应用。only-allow 通过获取系统环境运行时的信息,和预设好的参数信息进行对比,来限制预期外包管理器的使用。
参考文章 从 vue3 和 vite 源码中,我学到了一行代码统一规范团队包管理器的神器